﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reactive.Linq;
using Caliburn.Micro;
using Wulong.Phone.Dianping.Constants;
using Wulong.Phone.Dianping.Helpers;
using Wulong.Phone.Dianping.Models;
using Wulong.Phone.Dianping.Services;
using Wulong.Phone.Dianping.Utils;

namespace Wulong.Phone.Dianping.ViewModels
{
    public class SearchViewModel : PaginationViewModelBase
    {
        private IDisposable _disposable;
        private INavigationService _navigation;
        public SearchViewModel(INavigationService navigation)
        {
            _navigation = navigation;
            _cities = new ObservableCollection<City>();
            _channels = new ObservableCollection<Channel>();
            _searchCandidates = new ObservableCollection<Merchant>();
            SelectedResult = null;
            Keywords = string.Empty;
            if (Page < 1)
                Page = 1;
        }

        private string _keywords;
        public string Keywords
        {
            get { return _keywords; } 
            set
            {
                _keywords = value;
                NotifyOfPropertyChange(()=>Keywords);
            }
        }
        protected override void OnViewReady(object view)
        {
            base.OnViewReady(view);
            if (_cities.Count == 0)
                RenderCityPicker();
            if (_channels.Count == 0)
                LoadChannels();
        }
        private readonly ObservableCollection<City> _cities;
        public IEnumerable<City> Cities
        {
            get { return _cities; }
        }


        private readonly ObservableCollection<Channel> _channels;
        public IEnumerable<Channel> Channels
        {
            get { return _channels; }
        }

        private readonly ObservableCollection<Merchant> _searchCandidates;
        public IEnumerable<Merchant> SearchCandidates
        {
            get { return _searchCandidates; }
        }

        private City _selectedCity;
        public City SelectedCity
        {
            get { return _selectedCity; }
            set
            {
                _selectedCity = value;
                NotifyOfPropertyChange(() => SelectedCity);
            }
        }

        private Channel _selectedChannel;
        public Channel SelectedChannel
        {
            get { return _selectedChannel; }
            set
            {
                _selectedChannel = value;
                NotifyOfPropertyChange(() => SelectedChannel);
            }
        }

        private Merchant _selectedResult;
        public Merchant SelectedResult
        {
            get { return _selectedResult; }
            set
            {
                _selectedResult = value;
                NotifyOfPropertyChange(() => SelectedResult);
            }
        }

        public void LoadMore()
        {
            if (string.IsNullOrWhiteSpace(Keywords) ||
                SelectedCity == null ||
                SelectedChannel == null)
                return;
            IsBusy = true;
            CanLoadMore = false;
            _disposable=DianpingService
                .ObservableSearch
                (
                    Keywords,
                    SelectedCity.Code,
                    SelectedChannel.Id,
                    ++Page
                )
                .ObserveOnDispatcher()
                .Finally(() => IsBusy = false)
                .Subscribe
                (
                    item => _searchCandidates.Add(item),
                    error =>
                    {
                        MessageHelper.ShowErrorMessage();
                        --Page;
                    },
                    () =>
                    {
                        if (_searchCandidates.Count == CommonConstants.DefaultPageSize)
                            CanLoadMore = true;
                        NotifyOfPropertyChange(() => SearchCandidates);
                    }
                );
        }

        private void LoadChannels()
        {
            DianpingService
                .ObservableChannel(CityCode)
                .ObserveOnDispatcher()
                .Subscribe(item => _channels.Add(item),
                               ()=>
                                   {
                                       if (SelectedChannel == null)
                                           SelectedChannel = _channels[0];
                                   });
        }

        private void RenderCityPicker()
        {
            string myCityCode;
            bool hasValue = AppSettings.TryGetSetting(
                CommonConstants.MyCityStorageKey,
                out myCityCode);
            DianpingService
                .ObservableCity()
                .Subscribe(item =>
                {
                    _cities.Add(item);
                    if (SelectedCity != null || 
                        !hasValue || 
                        !item.Code.Equals(myCityCode)) return;
                    SelectedCity = item;
                });
        }

        public void Search()
        {
            if (string.IsNullOrWhiteSpace(Keywords) ||
                SelectedCity == null ||
                SelectedChannel == null)
                return;
            IsBusy = true;
            CanLoadMore = false;
            _searchCandidates.Clear();
            _disposable=DianpingService
                .ObservableSearch
                (
                    Keywords,
                    SelectedCity.Code,
                    SelectedChannel.Id
                )
                .ObserveOnDispatcher()
                .Finally(()=>IsBusy=false)
                .Subscribe
                (
                    item => _searchCandidates.Add(item),
                    () =>
                        {
                            if (_searchCandidates.Count >0)
                                CanLoadMore = true;
                            NotifyOfPropertyChange(() => SearchCandidates);
                        }
                );
        }

        public void MerchantDetail()
        {
            if (SelectedResult == null) return;
            _navigation
                .UriFor<MerchantPivotViewModel>()
                .WithParam(x => x.CityCode, SelectedCity.Code)
                .WithParam(x => x.MerchantId, SelectedResult.Id)
                .WithParam(x => x.ImageUrl, SelectedResult.ImageUrl.Replace("_s", "_m"))
                .WithParam(x => x.MerchantAvgPrice, SelectedResult.AvgPrice)
                .WithParam(x => x.MerchantOverallRating, SelectedResult.OverallRating)
                .Navigate();
        }

        protected override void OnDeactivate(bool close)
        {
            base.OnDeactivate(close);
            if(_disposable!=null)
                _disposable.Dispose();
        }
    }
}
